﻿// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
double getdis(Point p1, Point p2);
static int countNumber=0;
bool isCounted = false;
int labelTargets(Mat &src, Mat &mask, int thresh,vector<Point> &centers,int &counter);
Point p1 = Point(534, 281);
Point p2 = Point(734, 281);
Point p3 = Point(1222, 576);
Point p4 = Point(860, 576);
Mat GetROImage(Mat srcImage)
{

	for (int j = 0; j < 4; j++)
	{
		
		Point root_points[1][4];
		root_points[0][0] = p1;
		root_points[0][1] = p2;
		root_points[0][2] = p3;
		root_points[0][3] = p4;

		const Point* ppt[1] = { root_points[0] };
		int npt[] = { 4 };
		//  polylines(srcImage, ppt, npt, 1, 1, Scalar(0, 0, 0), 1, 8, 0);

		vector <Mat>mv;
		cv::Mat mask_ann, dst, dst1, dst2;
		srcImage.copyTo(mask_ann);
		mask_ann.setTo(cv::Scalar::all(0));
		fillPoly(mask_ann, ppt, npt, 1, Scalar(255, 255, 255));
		split(mask_ann, mv);
		srcImage.copyTo(dst, mv[0]);
		vector<Point> rectPoints = {}; //得到rectangle 的角点
		rectPoints.push_back(p1);
		rectPoints.push_back(p2);
		rectPoints.push_back(p3);
		rectPoints.push_back(p4);
		Rect rec = boundingRect(Mat(rectPoints));
		dst1 = dst(rec); //boundingRect(Mat(rectPoints))  //得到rectROImage
		return dst1;
	}
}
int main()
{
	VideoCapture cap;
	Mat frame;
	Mat mask;
	Mat srcImage;
	vector<Point>centers;
	vector<float>areas;

	cap.open("C:\\Users\\sika\\Documents\\csdncode\\999.mp4");
	int framecount=0;
	if (!cap.isOpened())
	{
		return -1;
	}
	Ptr<BackgroundSubtractorMOG2> bgsubtractor = createBackgroundSubtractorMOG2();
	
	int sum=0;
	while (1)
	{
		int key = waitKey(1);
		if (key == 'q' || key == 27) {
			return -1;
		}
		cap >> frame;

		//resize(frame, resizeImage,Size(frame.rows*0.5,frame.cols*0.5));
		if (frame.empty())
		{
			break;
		}
		if (key == 'w') {
			imwrite("C:\\Users\\sika\\Documents\\csdncode\\capture.jpg", frame);
		}
		Mat roiImage = GetROImage(frame);
		bgsubtractor->apply(roiImage, mask);
		
		threshold(mask, mask, 0, 255, THRESH_OTSU);
		
		medianBlur(mask, mask, 5);
		morphologyEx(mask, mask, MORPH_OPEN, getStructuringElement(MORPH_RECT, Size(5, 5)));
		morphologyEx(mask, mask, MORPH_CLOSE, getStructuringElement(MORPH_RECT, Size(5, 5)));
		morphologyEx(mask, mask, MORPH_ELLIPSE, getStructuringElement(MORPH_RECT, Size(5, 5)));
		Point point1 = p1;
		Point point2 = p2;
		Point point3 = p3;
		Point point4 = p4;
		line(frame, point1, point2, Scalar(0, 0, 0xff), 5);
		line(frame, point2, point3, Scalar(0, 0, 0xff), 5);
		line(frame, point3, point4, Scalar(0, 0, 0xff), 5);
		line(frame, point4, point1, Scalar(0, 0, 0xff), 5);
		
		
		//vector<Rect> old_rects = rects;
		int nTargets = labelTargets(roiImage, mask, 10000,centers,countNumber);
		string strnumber;
		stringstream ss;
		ss << countNumber;
		ss >> strnumber;
		line(roiImage, Point(0, 150), Point(roiImage.cols, 150), Scalar(0, 0, 255), 5);
		putText(roiImage, strnumber, Point(400, 100), CV_FONT_HERSHEY_PLAIN, 2, Scalar(0, 0xff, 0));
		
		imshow("roi",roiImage);
		imshow("mask", mask);
		
		imshow("video", frame);
		
		
	}
	cap.release();
	return 0;
}
double getdis(Point p1, Point p2) {
	double distance;
	distance = powf((p1.x - p2.x), 2) + powf((p1.y - p2.y), 2);
	distance = sqrtf(distance);
	return distance;
}

//int labelTargets(Mat &src, Mat &mask, int thresh, vector<Rect> &rects)
int labelTargets(Mat &src, Mat &mask, int thresh,vector<Point> &centers,int &counter) {
	Mat seg = mask.clone();
	vector<vector<Point>> cnts;
	findContours(seg, cnts, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	float area;
	Rect rect;
	int count = 0;
	string strCount;
	string strnumber;
	//rects.clear();
	for (int i = cnts.size() - 1; i >= 0; i--) {
		vector<Point>c = cnts[i];
		area = contourArea(c);
		if (area < thresh||area>50000) {
			
			continue;
		}
		
		rect = boundingRect(c);
		Point center = Point(rect.x + rect.width*0.5, rect.y + rect.height*0.5);
		circle(src, center, 5, Scalar(0, 0, 255));
		centers.push_back(center);
	//	areas.push_back(area);
		
		count++;
		stringstream ss;
		ss << counter;
		ss >> strCount;
	}
	if (centers.size() >= 3) {
		if (centers[2].y - centers[0].y < 0) {
			rectangle(src, rect, Scalar(0, 0, 255), 1);

		}
		if (centers[centers.size()-1].y < 150 && centers[0].y > 150 &&!isCounted) {
			if (centers[centers.size() - 1].y < centers[0].y) {
				counter += 1;
				isCounted = true;
			}
			/*isCounting = true;*/
		}
		for (int i = 1; i < centers.size() - 1; i++) {
			if (getdis(centers[i], centers[i - 1]) < 50) {
				line(src, centers[i], centers[i - 1], Scalar(0, 0, 255));
			}
			else {
				centers.clear();
				
				isCounted = false;
				break;
			}
		}

	}

	//
	//if (centers.size() > 2) {
	//	
	//}
	
	//centers.clear();
	return count;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
